home *** CD-ROM | disk | FTP | other *** search
/ Super PC 31 / Super PC 31 (Shareware).iso / spc / inter / speakf / fuente / speaker.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-07  |  12.3 KB  |  424 lines

  1. /*
  2.  
  3.     Play sound buffer
  4.     
  5. */
  6.  
  7. #include "netfone.h"
  8.  
  9. /*  GSMDECOMP  --  Uncompress the contents of a sound buffer using GSM.  */
  10.  
  11. static void gsmdecomp(sb)
  12.   struct soundbuf *sb;
  13. {
  14.     gsm_signal dst[160];
  15.     int i, j, l = 0;
  16.     char *dpx = ((char *) sb->buffer.buffer_val) + sizeof(short);
  17.     static char dcb[BUFL];
  18.     short declen = *((short *) sb->buffer.buffer_val);
  19.     
  20.     revshort(&declen);
  21.     if (declen <= 0 || declen > 1600) {
  22.         declen = 1600;
  23.     }
  24.     for (i = 0; i < sb->buffer.buffer_len - sizeof(short);
  25.                 i += sizeof(gsm_frame)) {
  26.         gsm_decode(gsmh, (gsm_byte *) dpx, dst);
  27.         dpx += sizeof(gsm_frame);
  28.         for (j = 0; j < 160; j++) {
  29.             dcb[l++] = audio_s2u(dst[j]);
  30.         }
  31.     }
  32.     _fmemcpy(sb->buffer.buffer_val, dcb, declen);
  33.     sb->buffer.buffer_len = declen;
  34. }
  35.  
  36. /*    ADPCMDECOMP  --  Decompress the contents of a sound buffer using ADPCM.  */
  37.  
  38. void adpcmdecomp( struct soundbuf *sb)
  39. {
  40. #define TINY_PACKETS 512
  41.     char *dp = (char *) sb->buffer.buffer_val;
  42.     unsigned char *sp;
  43.     static unsigned char dob[TINY_PACKETS * 2];
  44.     struct adpcm_state adpcm;
  45.  
  46.     /* Restore the decoder state from the copy saved in the packet,
  47.        independent of the byte order of the machine we're running on. */
  48.  
  49.     sp = (unsigned char *) dp + (sb->buffer.buffer_len - 3);
  50.     adpcm.valprev = (short) ((((int) sp[0]) << 8) | ((int) sp[1]));
  51.     adpcm.index = sp[2];
  52.     sb->buffer.buffer_len -= 3;
  53.  
  54.     adpcm_decoder_u(dp, dob, (int) (sb->buffer.buffer_len * 2), &adpcm);
  55.     sb->buffer.buffer_len *= 2;
  56.     _fmemcpy(dp, dob, (size_t) sb->buffer.buffer_len);
  57. }
  58.  
  59. /*    LPCDECOMP  --  Uncompress the contents of a sound buffer using LPC.  */
  60.  
  61. static void lpcdecomp(struct soundbuf *sb)
  62. {
  63.     int i, j, l = 0;
  64.     char *dpx = ((char *) sb->buffer.buffer_val) + sizeof(short);
  65.     static char dcb[1800];
  66.     short declen = *((short *) sb->buffer.buffer_val);
  67.  
  68.     if (declen <= 0 || declen > 1800) {
  69.         declen = 1800;
  70.     }
  71.     for (i = 0; l < declen; i += sizeof(lpcparams_t)) {
  72.         lpcparams_t *lp = (lpcparams_t *) (dpx + i);
  73.         
  74.         revshort(&(lp->period)); 
  75.         j = lpc_synthesize(lp, 1.0, dcb + l);
  76.         l += j;
  77.     }
  78.     _fmemcpy(sb->buffer.buffer_val, dcb, declen);
  79.     sb->buffer.buffer_len = declen;
  80. }
  81.  
  82. /*  PLAYSOUND  --  Play a sound buffer, decrypting and decompressing
  83.                    as required.  */
  84.                    
  85. void playSound(HWND hWnd, LPCLIENT_DATA pClientData, soundbuf *d,
  86.                int bitsPerSample, int samplesPerSecond)
  87. {
  88.     LPWAVEHDR wh;
  89.     short FAR *sbuf;
  90.     unsigned char _huge *ulp;
  91.     WORD stat;
  92.     int i, len, dline;
  93.     char *val;
  94.     static unsigned char auxbuf[BUFL + 2];
  95.     char bbuf[8], tbuf[8];
  96.     
  97.     /*    If the message queue is close to exhaustion, ditch the output
  98.         buffer to avoid a hangup due to queue overflow.  */
  99.         
  100.     if (outputPending >= ((3 * messageQueueSize) / 4)) {
  101.         propeller(IDC_PH_INPUT_LOST, ++inputPacketsLost);
  102.         return;
  103.     }
  104.     
  105.     if (pClientData != NULL) {
  106.         pClientData->debugReq = (d->compression & fDebug) ? TRUE : FALSE;
  107.         if (pClientData->debugReq && !IsIconic(hWnd)) {
  108.             HDC hdc = GetDC(hWnd);
  109.             char buf[80];
  110.                 
  111.             wsprintf(buf, Format(44), d->buffer.buffer_len);
  112.             lstrcat(buf,
  113.                     ((d->compression & (fComp2X | fCompGSM)) ==
  114.                                          (fComp2X | fCompGSM)) ?
  115.                                          rstring(IDS_T_GSM_2X) :
  116.                     ((d->compression & (fComp2X | fCompADPCM)) ==
  117.                                          (fComp2X | fCompADPCM)) ?
  118.                                          rstring(IDS_T_ADPCM_2X) :
  119.                     ((d->compression & (fComp2X | fCompLPC)) ==
  120.                                          (fComp2X | fCompLPC)) ?
  121.                                          rstring(IDS_T_LPC_2X) :
  122.                     ((d->compression & fComp2X) ? rstring(IDS_T_2X) :
  123.                     ((d->compression & fCompADPCM) ? rstring(IDS_T_ADPCM) :
  124.                     ((d->compression & fCompLPC) ? rstring(IDS_T_LPC) :
  125.                     ((d->compression & fCompGSM) ? rstring(IDS_T_GSM) :  "")))));
  126.             lstrcat(buf, rstring(IDS_SP_BYTES_PERIOD));
  127.     
  128.             TextOut(hdc, 1 * tmAveCharWidth, 5 * tmHeight, buf, strlen(buf));
  129.             for (i = 6; i < 10; i++) {
  130.                 TextOut(hdc, 1 * tmAveCharWidth, i * tmHeight, blankit, strlen(blankit));
  131.             }
  132.             ReleaseDC(hWnd, hdc);                
  133.         }
  134.     }
  135.     
  136.     
  137.     wh = (LPWAVEHDR) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE,
  138.             sizeof(WAVEHDR));
  139.     if (wh == NULL) {
  140.         return;
  141.     }
  142.     
  143.     /* Perform requested decryption and decompression of the
  144.        received data. */
  145.        
  146.     len = (int) d->buffer.buffer_len;
  147.     val = d->buffer.buffer_val;
  148.  
  149.     /* If the fSetDest bit is on, turn up the volume all the way
  150.        if fDestJack is set.  This indicates an attempt to get the
  151.        user's attention, even in case he's turned the volume all
  152.        the way down. */
  153.  
  154.     if (d->compression & fSetDest) {
  155.         if (!(d->compression & fDestJack)) {
  156.             waveOutSetVolume((UINT) hWaveOut, (DWORD) MAKELONG(0xFFFF, 0xFFFF));
  157.         }
  158.     }
  159.  
  160.     dline = 6;    
  161.  
  162.     /* If message is encrypted, decrypt. */
  163.  
  164.     if ((d->compression & fEncOTP) && (pClientData->otpFileName[0])) {
  165.         int i;
  166.  
  167.         if (pClientData->debugReq) {
  168.             if (!IsIconic(hWnd)) {
  169.                 HDC hdc = GetDC(hWnd);
  170.                 
  171.                 WinPrintf(hdc, dline++, 1, 
  172.                     rstring(IDS_T_KEY_FILE_STATUS), len);
  173.                 ReleaseDC(hWnd, hdc);        
  174.             }
  175.         }
  176.         for (i = 0; i < len; i ++) {
  177.             val[i] ^= pClientData->otp[i];
  178.         }
  179.     }
  180.     if ((d->compression & fEncPGP)) {
  181.         unsigned short iv[4];
  182.         int slen = (len + 7) & (~7);
  183.         char twibble[16];
  184.         
  185.         /*    Special gimmick: if we receive a PGP-encrypted packet while
  186.             we're still waiting for PGP to complete decrypting the session
  187.             key, ditch it.  This is a lot easier on the user's ears when
  188.             he's trying furiously to enter the private key phrase.  */
  189.             
  190.         if (pClientData->pgpFileName[0] != 0) {
  191.             propeller(IDC_PH_INPUT_LOST, ++inputPacketsLost);
  192.             return;
  193.         } else if (pClientData->pgpkey[0] != 0) { 
  194.             _fmemcpy(twibble, pClientData->pgpkey + 1, 16);
  195.             _fmemset(iv, 0, sizeof(iv));
  196.             initcfb_idea(iv, twibble, TRUE);
  197.     
  198.             if (pClientData->debugReq) {
  199.                 if (!IsIconic(hWnd)) {
  200.                     HDC hdc = GetDC(hWnd);
  201.                     
  202.                     WinPrintf( hdc, dline++, 1, 
  203.                         rstring(IDS_T_PGP_STATUS), len);
  204.                     ReleaseDC(hWnd, hdc);        
  205.                 }
  206.             }
  207.             ideacfb(val, slen);
  208.             close_idea();
  209.         }
  210.     }
  211.     
  212.     if ((d->compression & fEncIDEA) && pClientData->ideaKeyString[0]) {
  213.         unsigned short iv[4];
  214.         int slen = (len + 7) & (~7);
  215.         char twibble[16];
  216.         
  217.         _fmemcpy(twibble, pClientData->ideakey + 1, 16);
  218.         _fmemset(iv, 0, sizeof(iv));
  219.         initcfb_idea(iv, twibble, TRUE);
  220.  
  221.         if (pClientData->debugReq) {
  222.             if (!IsIconic(hWnd)) {
  223.                 HDC hdc = GetDC(hWnd);
  224.                 
  225.                 WinPrintf( hdc, dline++, 1, 
  226.                     rstring(IDS_T_IDEA_STATUS), len);
  227.                 ReleaseDC(hWnd, hdc);        
  228.             }
  229.         }
  230.         ideacfb(val, slen);
  231.         close_idea();
  232.     }
  233.  
  234.     if ((d->compression & fEncDES) && pClientData->desKeyString[0]) {
  235.         int i;
  236.         char twibble[8];
  237.         
  238.         _fmemcpy(twibble, pClientData->deskey + 1, 8);
  239.         setkey(twibble);
  240.  
  241.         if (pClientData->debugReq) {
  242.             if (!IsIconic(hWnd)) {
  243.                 HDC hdc = GetDC(hWnd);
  244.                 
  245.                 WinPrintf( hdc, dline++, 1, 
  246.                     rstring(IDS_T_DES_STATUS), len);
  247.                 ReleaseDC(hWnd, hdc);        
  248.             }
  249.         }
  250.         for (i = 0; i < len; i += 8) {
  251.             memcpy(tbuf, val + i, 8);
  252.             dedes(val + i);
  253.  
  254.             /* Reverse cipher block chaining. */
  255.  
  256.             if (i > 0) {
  257.                 int j;
  258.  
  259.                 for (j = 0; j < 8; j++) {
  260.                     val[(i + j)] ^= bbuf[j];
  261.                 }
  262.             }
  263.             memcpy(bbuf, tbuf, 8);
  264.         }
  265.     }
  266.  
  267.     /* If message is compressed, decompress appropriately. */
  268.  
  269.     if (d->compression & fCompGSM) {
  270.         gsmdecomp(d);
  271.         len = (int) d->buffer.buffer_len;
  272.     }
  273.     
  274.     if (d->compression & fCompADPCM) {
  275.         adpcmdecomp(d);
  276.         len = (int) d->buffer.buffer_len;
  277.     }
  278.     
  279.     if (d->compression & fCompLPC) {
  280.         lpcdecomp(d);
  281.         len = (int) d->buffer.buffer_len;
  282.     }
  283.  
  284.     if (d->compression & fComp2X) {
  285.         int i;
  286.         register char *ab = auxbuf;
  287.  
  288.         for (i = 0; i < len; i++) {
  289.             *ab++ = i == 0 ? *val :
  290.                 (audio_s2u((audio_u2s(*val) + audio_u2s(val[-1])) / 2));
  291.             *ab++ = *val++;
  292.         }
  293.         len *= 2;
  294.         val = auxbuf;
  295.     }
  296.     
  297.     if (samplesPerSecond == 11025) {
  298.         if (bitsPerSample == 16) {       
  299.             
  300.             /* Convert the resulting u-law samples in the sound buffer
  301.                to 16 bit signed linear format. */
  302.                
  303.             wh->lpData = (LPSTR) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE,
  304.                 (DWORD) (((BUFL * ((DWORD) sizeof(short)) * 12) / 8))); 
  305.             if (wh->lpData == NULL) {
  306.                 GlobalFreePtr(wh);
  307.                 return;
  308.             }
  309.             sbuf = (short FAR *) wh->lpData;
  310.             ulp = (unsigned char *) val;
  311.             
  312.             for (i = 0; i < len; i++) {
  313.                 int j = i & 7;
  314.                 *sbuf++ = audio_u2s(*ulp);
  315.                 //    This should be written out for better optimisation
  316.                 if (j > 0 && !(j & 1)) {
  317.                     *sbuf++ = audio_u2s(*ulp);
  318.                 } else if (j % 320 == 319) {
  319.                     *sbuf++ = audio_u2s(*ulp);
  320.                 }
  321.                 ulp++; 
  322.             }
  323.             wh->dwBufferLength = wh->dwBytesRecorded =
  324.                 (((LPSTR) sbuf) - wh->lpData);
  325.         } else if (bitsPerSample == 8) {
  326.             BYTE FAR *bbuf;
  327.             
  328.             /* Convert the resulting u-law samples in the sound buffer
  329.                to 8 bit PCM format. */
  330.                
  331.             wh->lpData = (LPSTR) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE,
  332.                 (DWORD) (((BUFL * ((DWORD) sizeof(short)) * 12) / 16))); 
  333.             if (wh->lpData == NULL) {
  334.                 GlobalFreePtr(wh);
  335.                 return;
  336.             }
  337.             bbuf = (BYTE FAR *) wh->lpData;
  338.             ulp = (unsigned char *) val;
  339.     
  340.             for (i = 0; i < len; i++) {
  341.                 int j = i & 7;
  342.                 *bbuf++ = audio_u2c(*ulp);
  343.                 //    This should be written out for better optimisation
  344.                 if (j > 0 && !(j & 1)) {
  345.                     *bbuf++ = audio_u2c(*ulp);
  346.                 } else if (j % 320 == 319) {
  347.                     *bbuf++ = audio_u2c(*ulp);
  348.                 }
  349.                 ulp++; 
  350.             }
  351.             wh->dwBufferLength = wh->dwBytesRecorded =
  352.                 (((LPSTR) bbuf) - wh->lpData);
  353.         }
  354.     } else {    // samplesPerSecond == 8000
  355.         if (bitsPerSample == 16) {       
  356.             
  357.             /* Convert the resulting u-law samples in the sound buffer
  358.                to 16 bit signed linear format. */
  359.                
  360.             wh->lpData = (LPSTR) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE,
  361.                 (DWORD) (len * sizeof(short))); 
  362.             if (wh->lpData == NULL) {
  363.                 GlobalFreePtr(wh);
  364.                 return;
  365.             }
  366.             sbuf = (short FAR *) wh->lpData;
  367.             ulp = (unsigned char *) val;
  368.             
  369.             for (i = 0; i < len; i++) {
  370.                 *sbuf++ = audio_u2s(*ulp++);
  371.             }
  372.             wh->dwBufferLength = wh->dwBytesRecorded =
  373.                 (((LPSTR) sbuf) - wh->lpData);
  374.         } else if (bitsPerSample == 8) {
  375.             BYTE FAR *bbuf;
  376.             
  377.             /* Convert the resulting u-law samples in the sound buffer
  378.                to 8 bit PCM format. */
  379.                
  380.             wh->lpData = (LPSTR) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE,
  381.                 (DWORD) (len * sizeof(BYTE))); 
  382.             if (wh->lpData == NULL) {
  383.                 GlobalFreePtr(wh);
  384.                 return;
  385.             }
  386.             bbuf = (BYTE FAR *) wh->lpData;
  387.             ulp = (unsigned char *) val;
  388.     
  389.             for (i = 0; i < len; i++) {
  390.                 *bbuf++ = audio_u2c(*ulp++);
  391.             }
  392.             wh->dwBufferLength = wh->dwBytesRecorded =
  393.                 (((LPSTR) bbuf) - wh->lpData);
  394.         }
  395.     }
  396.     
  397.     //    Give the answering machine a chance to save the buffer
  398.     
  399.     if (!(d->compression & fPlayback)) {
  400.         answerSave(pClientData->inetSock.sin_addr, pClientData->szHost, d);
  401.     }
  402.     
  403.     wh->dwFlags = 0;
  404.     waveOutPrepareHeader(hWaveOut, wh, sizeof(WAVEHDR));
  405.     stat = waveOutWrite(hWaveOut, wh, sizeof(WAVEHDR));
  406.     if (stat == 0) {
  407.         outputPending++;
  408.         if (hDlgPropeller != NULL) {
  409.             char s[80];
  410.                     
  411.             wsprintf(s, outputPending == 0 ? Format(6) : Format(7),
  412.                         outputPending);
  413.             SetDlgItemText(hDlgPropeller, IDC_PH_AUDIO_OUT_QUEUE, s);
  414.         }
  415.     } else {    
  416.         char et[MAXERRORLENGTH];
  417.             
  418.         waveOutGetErrorText(stat, et, sizeof et);
  419.         waveOutUnprepareHeader(hWaveOut, wh, sizeof(WAVEHDR));
  420.         GlobalFreePtr(wh);
  421.         MsgBox(hWnd, MB_OK | MB_ICONEXCLAMATION, Format(45), et);
  422.         return;
  423.     }
  424. }